# 任务调度器封装
from apscheduler.schedulers.background import BackgroundScheduler
from utils.config import get_config
import threading
from models.db import MGClient
from plugins import get_plugin_by_name


class SchedulerManager:
    """
    添加唯一实例化保护。
    注：Flask调试模式会启用监视进程，此方式无法避免多个SchedulerManager实例共存问题
    示例代码中关于数据库操作未使用models.db封装的函数，实际应用时封装好所有操作
    """

    _instance = None

    def __new__(cls):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        # 防止重复初始化
        if not hasattr(self, "initialized"):
            self.scheduler = BackgroundScheduler()
            self.lock = threading.Lock()
            self.task_interval = get_config('task_interval', 60)
            self.tasks_collection = MGClient.get_client()
            self.initialized = True

    def start(self):
        self.scheduler.start()
        self._schedule_tasks()

    def shutdown(self):
        self.scheduler.shutdown()

    def _schedule_tasks(self):
        # 从数据库中读取状态为active的job，添加到调度器
        active_tasks = self.tasks_collection.find({'status': 'active'})
        for task in active_tasks:
            task_id = task['task_id']
            interval = task['interval']
            plugin_name = task['plugin_name']

            # 防止重复添加
            if not self.scheduler.get_job(task_id):
                # 动态获取任务函数
                plugin_module = get_plugin_by_name(plugin_name)
                func = getattr(plugin_module, "run") if plugin_module else None
                # 向调度器中添加job
                if func:
                    self.scheduler.add_job(func, 'interval', seconds=interval,
                                           id=task_id, replace_existing=True,
                                           args=[task_id, interval])
                    print(f"启动时调度器中的任务： {self.scheduler.get_jobs()}")

    def update_interval(self, new_interval, task_id):
        with self.lock:
            # 更新数据库记录
            result = self.tasks_collection.update_one(
                {'task_id': task_id},
                {'$set': {'interval': new_interval}}
            )
            # 仅在时间间隔发生更新时更新调度器
            if result.modified_count > 0:
                job = self.scheduler.get_job(task_id)
                if job:
                    self.scheduler.remove_job(job.id)

            # 添加新间隔job
            task_info = self.tasks_collection.find_one({'task_id': task_id})
            plugin_module = get_plugin_by_name(task_info["plugin_name"])
            func = getattr(plugin_module, "run") if plugin_module else None
            if func and task_info.get("status") == "active":
                self.scheduler.add_job(func, 'interval', seconds=new_interval,
                                       id=task_id, replace_existing=True,
                                       args=[task_id, new_interval])

    def remove_job(self, task_id):
        checked_job = self.scheduler.get_job(task_id)
        if checked_job:
            self.scheduler.remove_job(checked_job.id)
            with self.lock:
                self.tasks_collection.update_one(
                    {'task_id': task_id},
                    {'$set': {'status': "dormant"}}
                )
            return True
        return False


# 全局实例
schedule = SchedulerManager()
